package com.site.util.extremetable;

import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.criterion.Order;


public class OrderByUtil {
	/**
	 * 构造Criteria的排序条件
	 * 
	 * @param criteria
	 *            Criteria实例.
	 * @param sortMap
	 *            排序条件.
	 * @param entity
	 *            entity对象,用于使用反射来获取某些属性信息
	 * @throws NoSuchMethodException 
	 * @throws InvocationTargetException 
	 * @throws IllegalAccessException 
	 */
	public static void sortCriteria(Criteria criteria, Map sortMap,
			Object entity) {
		if (!sortMap.isEmpty()) {
			for (Iterator it = sortMap.keySet().iterator(); it.hasNext();) {
				Object o = it.next();
				String fieldName = o.toString();
				String orderType = sortMap.get(fieldName).toString();

				// 处理嵌套属性如category.name,modify_user.id,暂时只处理一级嵌套
				if (fieldName.indexOf('.') != -1) {
					String alias = StringUtils.substringBefore(fieldName, ".");
					String aliasType = alias;
					
					try{
					aliasType = PropertyUtils.getProperty(entity, alias)
							.getClass().getName();
					}
					catch (IllegalAccessException laex){
						throw new RuntimeException(laex.toString());
					}
					catch (InvocationTargetException laex){
						throw new RuntimeException(laex.toString());
					}
					catch (NoSuchMethodException laex){
						throw new RuntimeException(laex.toString());
					}
					criteria.createAlias(aliasType, alias);
				}

				if ("asc".equalsIgnoreCase(orderType)) {
					criteria.addOrder(Order.asc(fieldName));
				} else {
					criteria.addOrder(Order.desc(fieldName));
				}
			}
		}
	}

	/**
	 * 构造sql或者hql的排序条件
	 * 
	 * @param sql
	 *            sql或者hql语句.
	 * @param sortMap
	 *            排序条件.
	 */
	public static String sortSql(String hql, Map sortMap) {
		StringBuffer buffer = new StringBuffer(hql);
		if (!sortMap.isEmpty()) {
			buffer.append(" order by ");
			int i = 0;
			for (Iterator it = sortMap.keySet().iterator(); it.hasNext();) {
				Object o = it.next();
				String fieldName = o.toString();
				String orderType = sortMap.get(fieldName).toString();
				// 获得表的别名
				String tableName = getTableName(hql, fieldName);

				if ("asc".equalsIgnoreCase(orderType)) {
					if (i == 0)
						buffer.append(tableName).append(fieldName).append(
								" asc");
					else
						buffer.append(",").append(tableName).append(fieldName)
								.append(" asc");
				} else {
					if (i == 0)
						buffer.append(tableName).append(fieldName).append(
								" desc");
					else
						buffer.append(",").append(tableName).append(fieldName)
								.append(" desc");
				}
				i++;
			}
		}
		return buffer.toString();
	}

	/**
	 * 根据字段名从sql中获得表的别名
	 * 
	 * @param sql
	 *            sql语句.
	 * @param fieldName
	 *            字段名.
	 */
	public static String getTableName(String hql, String fieldName) {
		hql = StringUtils.substringBetween(hql.toLowerCase(), "select", "from");
		if (hql == null)
			hql = "";
		int endIndex = hql.indexOf(fieldName.toLowerCase());
		String tableName = "";
		if (endIndex != -1) {
			String subhql = hql.substring(0, endIndex);
			int beginIndex = subhql.lastIndexOf(",");
			tableName = hql.substring(beginIndex + 1, endIndex).trim();
		}
		return tableName;
	}
	
	/**
	 * 给criteria加上order by
	 * @param criteria
	 * @param sortMap
	 */
	public static void addCriteriaOrder(Criteria criteria,Map<String, String> sortMap) {
		Set<String> keyset=sortMap.keySet();
		for (Iterator iterator = keyset.iterator(); iterator.hasNext();) {
			String fieldName = (String) iterator.next();
			String orderByType=sortMap.get(fieldName);
			if("asc".equalsIgnoreCase(orderByType)){
				criteria.addOrder(Order.asc(fieldName));
			}else if("desc".equalsIgnoreCase(orderByType)){
				criteria.addOrder(Order.desc(fieldName));
			}
		}
		
	}

}
